import type { ApiUserTokenRes } from '@/api/access'
import type { UserInfo } from '@/services/user/type'
import { ref, readonly, computed, createVNode } from 'vue'
import { defineStore } from 'pinia'
import { Modal } from 'ant-design-vue'
import { ExclamationCircleOutlined } from '@ant-design/icons-vue'
import router from '@/router'
import xUserService from '@/services/user'
import { userPhoneLogin, userAccountLogin, getUserInfo, refreshAccessToken } from '@/api/access'

/**
 * 用户管理
 *
 * @description 管理用户与Token数据功能
 */
export const useUserStore = defineStore('user', () => {
  // 用户信息
  const userInfo = ref<UserInfo>(xUserService.getInstance().getUserInfo())
  // 弹窗锁（防止多次弹出）
  const confirmLock = ref<boolean>(false)

  // ----- Getters -----

  const isLogin = computed(() => !!userInfo?.value.uid)

  // ----- Actions -----

  /**
   * 用户登录（账号）
   *
   * @param passport 账号
   * @param password 密码
   * @returns
   */
  const loginByAccount = async (passport: string, password: string) => {
    return new Promise<boolean>(async (resolve, reject) => {
      try {
        const loginRes = await userAccountLogin({
          passport,
          password,
          deviceId: xUserService.getInstance().getDeviceId(),
        })
        // 注：这里需要首先将登录后获取的token存储，以方便后续获取用户信息
        // 也可以通过修改后端api，在登录后一并返回用户信息，减少一次请求
        setUserToken(loginRes)
        const isSuccess = await refreshUserInfo(false)
        resolve(isSuccess)
      } catch (e) {
        reject(e)
      }
    })
  }

  /**
   * 用户登录（短信）
   *
   * @param phone 手机号
   * @param code 验证码
   */
  const loginByPhone = async (phone: string, code: string) => {
    return new Promise<boolean>(async (resolve, reject) => {
      try {
        const loginRes = await userPhoneLogin({
          phone,
          code,
          deviceId: xUserService.getInstance().getDeviceId(),
        })
        // 注：这里需要首先将登录后获取的token存储，以方便后续获取用户信息
        // 也可以通过修改后端api，在登录后一并返回用户信息，减少一次请求
        setUserToken(loginRes)
        const isSuccess = await refreshUserInfo(false)
        resolve(isSuccess)
      } catch (e) {
        reject(e)
      }
    })
  }

  /**
   * 刷新用户信息
   *
   * @param needLogin 开启后只会在已登录的情况下执行请求
   * @returns
   */
  const refreshUserInfo = async (needLogin: boolean = true) => {
    return new Promise<boolean>(async (resolve, reject) => {
      try {
        if (!needLogin || isLogin.value) {
          const infoRes = await getUserInfo()
          setUserInfo(infoRes.data)
          resolve(true)
        } else {
          resolve(false)
        }
      } catch (e) {
        reject(e)
      }
    })
  }

  /**
   * 获取访问Token
   *
   * @returns
   */
  const getAccessToken = () => {
    return xUserService.getInstance().getAccessToken()
  }

  /**
   * 刷新TOKEN
   *
   * @returns
   */
  const refreshToken = async () => {
    return new Promise<ApiUserTokenRes>(async (resolve, reject) => {
      try {
        const tokenRes = await refreshAccessToken({
          uid: userInfo.value.uid,
          deviceId: xUserService.getInstance().getDeviceId(),
          refreshToken: xUserService.getInstance().getRefreshToken(),
        })
        setUserToken(tokenRes)
        resolve(tokenRes)
      } catch (e) {
        reject(e)
      }
    })
  }

  /**
   * 设置用户信息
   *
   * @param info 用户信息
   */
  const setUserInfo = (info: UserInfo) => {
    xUserService.getInstance().setUserInfo(info)
    userInfo.value = xUserService.getInstance().getUserInfo()
  }

  /**
   * 设置用户TOKEN
   *
   * @param token TOKEN
   */
  const setUserToken = (token: ApiUserTokenRes) => {
    xUserService
      .getInstance()
      .setUserToken(token.data.accessToken, token.data.refreshToken, token.data.expires)
  }

  /**
   * 清空用户信息（包括token）
   */
  const clearUserInfo = () => {
    xUserService.getInstance().clearUserData()
    userInfo.value = xUserService.getInstance().getUserInfo()
  }

  /**
   * 退出确认
   *
   * @param content 消息
   * @param lock 是否锁定（强制确认）
   */
  const logoutConfirm = (content: string, lock: boolean) => {
    if (!confirmLock.value) {
      const onOk = () => {
        clearUserInfo()
        confirmLock.value = false
        router.push({
          name: 'Login',
        })
      }
      if (lock) {
        Modal.error({
          title: '系统消息',
          content,
          maskClosable: false,
          keyboard: false,
          closable: false,
          onOk,
        })
      } else {
        Modal.confirm({
          title: '系统消息',
          icon: createVNode(ExclamationCircleOutlined),
          content,
          onOk,
          onCancel: () => {
            confirmLock.value = false
          },
        })
      }
      confirmLock.value = true
    }
  }

  return {
    /** getter: 用户完整信息 */
    readUserInfo: readonly(userInfo),
    /** getter: 是否已登录 */
    isLogin,
    /** action: 用户登录（账号） */
    loginByAccount,
    /** action: 用户登录（短信） */
    loginByPhone,
    /** action: 获取访问Token */
    getAccessToken,
    /** action: 刷新用户信息（未登录不操作） */
    refreshUserInfo,
    /** action: 刷新TOKEN */
    refreshToken,
    /** action: 清空用户信息（包括token） */
    clearUserInfo,
    /** action: 退出确认 */
    logoutConfirm,
    /** action: 清空本地存储 */
    clearLocalStorage: xUserService.getInstance().clearLocalStorage,
  }
})
